//
//  UserModel.h
//  SansecSign
//
//  Created by swxa@sasaliubobo on 16/11/24.
//  Copyright © 2016年 swxa@saasliubobo. All rights reserved.
//

#import <Foundation/Foundation.h>

//#import "P7Util.h"ReadFile
@interface SWXA_UserModel : NSObject


#pragma mark - SDK版本号

+(NSDictionary *)getVersion;


//json字符串转为字典
+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString;

//做哈希(SM3)并返回OC串（base64编码后）
+(NSString *)getk:(NSString *)k;
+(NSData *)getSM3Hash:(NSData *)k;
/**
 获取设备号

 @return 设备号
 */
+(NSString *)getUDID;

/**
 SM3哈希  兼容预处理

 @param plian 明文
 @param publicKey 预处理传入公钥（base64编码） / 否则传入nil
 @param bl 明文是否base64编码
 @return 哈希值
 */
+(NSData *) SM3:(NSData *) plian publicKey:(NSString *)publicKey base64:(BOOL)bl;
#pragma mark - 手机盾2.0.0


#pragma mark -注册密钥 SM2-256 RSA-1024 RSA-2048
/** 生成pkcs10 证书请求 dn项说明  格式：/CN=参数1/O=参数2/OU=参数3……
 * 例如："/O=swxa/CN=dkp/emailAddress=slflfe@qq.com/OU=plat/L=jn/ST=sd/C=CN"  严格按照格式来，不然p10 格式不合法
 * CN: 通用名称，域名  Common Name 中间不能有空格 汉字
 * O:  组织          Organization 中间不能有空格 汉字
 * OU: 部门          Organizational Unit
 * ST:  省份          State
 * L:  城市          Locality
 * C:  国家          Country
 */
/**
 *  注册密钥
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"appId":        @"**********", //应用id
 *             @"companyId":    @"**********", //公司id
 *             @"dn":           @"**********", //dn
 *             @"keyType":      @"**********", //密钥类型
 *             @"keyLen":       @"**********", //密钥长度
 *             @"secretKey":    @"**********", //secretKey
 *             @"username":     @"**********", //用户名
 *             @"pin":          @"**********", //PIN码
 *                   };
 *  @param successBlock 请求成功后的回调
 *  @param errorBlock 请求失败后的回调
 */

+(void)registSecretWithDic:(NSDictionary *)data andSuccess:(void (^)(NSDictionary * successData))successBlock error:(void (^)(NSError *error))errorBlock;

#pragma mark 修改PIN码
/**
 *  修改PIN码
 * data = @{
 *      @"companyId"  公司id
 *      @"username"   用户名
 *      @"keyType"    密钥类型 (SM2/RSA1024/RSA2048)
 *      @"keyLen"     密钥长度 (256/1024/2048)
 *      @"pin"        旧Pin码
 *      @"newpin"     新PIN码
 *      @"secretKey"  secretKey
 *      }
 *  successData: 返回数据
 */

+(void)ChangePINWithDic:(NSDictionary *)data andSuccess:(void (^)(NSDictionary * successData))successBlock error:(void (^)(NSError *error))errorBlock;


#pragma mark 验证PIN码
/**
 *  验证PIN码
 * data = @{
 *      @"companyId"  公司id
 *      @"username"   用户名
 *      @"keyType"    密钥类型 (SM2/RSA1024/RSA2048)
 *      @"keyLen"     密钥长度 (256/1024/2048)
 *      @"pin"        旧Pin码
 *      @"secretKey"  secretKey
 *      }
 *  successData: 返回数据
 */

+(void)CheckPINWithDic:(NSDictionary *)data andSuccess:(void (^)(NSDictionary * successData))successBlock error:(void (^)(NSError *error))errorBlock;


#pragma mark 签名
/**
 *  签名
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"appId"         @"**********"  //appId
 *             @"companyId":    @"**********", //公司id
 *             @"keyType":      @"**********", //密钥类型
 *             @"keyLen":       @"**********", //密钥长度
 *             @"e":            @"**********", //哈希值（base64编码后 RSA签名时，外部传入哈希值，内部会做pkcs1#填充）
 *             @"username":     @"**********", //用户名
 *             @"secretKey":    @"*********", //secretKey
 *             @"pin":          @"*********", //pin
 *                   };
 *  @param successBlock 请求成功后的回调
 *  @param errorBlock 请求失败后的回调
 */
+(void)signWithData:(NSDictionary *)data andSuccess:(void (^)(NSDictionary * successData))successBlock error:(void (^)(NSError *error))errorBlock;


#pragma mark 服务器验签
/**
 *  服务器验签
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"companyId":    @"**********", //公司id
 *             @"keyType":      @"**********", //密钥类型
 *             @"keyLen":       @"**********", //密钥长度
 *             @"e":            @"**********", //明文哈希
 *             @"signData":     @"**********", //签名值
 *             @"username":     @"**********", //用户名
 *             @"secretKey":    @"*********", //secretKey
 *                   };
 *  @param successBlock 请求成功后的回调
 *  @param errorBlock 请求失败后的回调
 */
+(void)verifyWithSever:(NSDictionary *)data andSuccess:(void (^)(NSDictionary *))successBlock error:(void (^)(NSError *error))errorBlock;

#pragma mark 本地验签
/**
 *  本地验签
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"keyType":      @“*********”, //密钥类型
 *             @"keyLen":       @“*********”, //密钥长度
 *             @"e":            @“*********”, //处理后的明文信息
 *             @"signData":     @"*********", //签名值
 *             @"username":     @“*********”, //username
 *                   };
 *  return：successData
 */
+(NSDictionary *)verifyWithLocal:(NSDictionary *)data;

#pragma mark 密钥是否存在
/**
 *  密钥是否存在
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"companyId":    @"*********", //公司id
 *             @"keyType":      @"*********", //密钥类型
 *             @"keyLen":       @"*********", //密钥长度
 *             @"secretKey":    @"*********", secretKey
 *             @"username":     @"*********", //用户名
 *                   };
 *  @param successBlock 请求成功后的回调
 *  @param errorBlock 请求失败后的回调
 */
+(void)keyExist:(NSDictionary *)data andSuccess:(void (^)(NSDictionary *))successBlock error:(void (^)(NSError *error))errorBlock;


#pragma mark - 获取本地手机盾用户
+(NSDictionary *)getLocalUser;

#pragma mark - 获取本地公钥
+(NSString *)getPublic:(NSString *)username keyType:(NSString *)keyType;

#pragma mark - 生成p10
/** 生成pkcs10 证书请求  格式：/CN=参数1/O=参数2/OU=参数3……
 * 例如："/O=swxa/CN=dkp/emailAddress=slflfe@qq.com/OU=plat/L=jn/ST=sd/C=CN"  严格按照格式来，不然p10 格式不合法
 * CN: 通用名称，域名  Common Name 中间不能有空格 汉字
 * O:  组织          Organization 中间不能有空格 汉字
 * OU: 部门          Organizational Unit
 * ST:  省份          State
 * L:  城市          Locality
 * C:  国家          Country
 */
/**
 *  生成p10
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"appId"           @"**********"  //appId
 *             @"companyId":      @"1000**",      //companyId
 *             @"keyLen":         @"*********",   //算法长度
 *             @"keyType":        @"*********",   //算法类型   SM2 RSA1024 RSA2048
 *             @"dn":             @"*********",   //dn信息 长度控制在255内
 *             @"hashAlg":        @"*********",   //哈希算法 SHA1，SHA256，SHA384，SHA512，SHA224,MD5
 *             @"username":       @"*********"    // 用户名
 *             @"secretKey":      @"*********",   //secretKey
 *             @"pin":            @"*********", //pin
 *                   };
 *  @param successBlock 请求成功后的回调
 *  @param fail 请求失败后的回调
 */

+(void )getP10:(NSDictionary *)data successBlock:(void (^)(id))successBlock fail:(void (^)(NSError *))fail;



#pragma  mark  导入p10
/**
 *  导入p10
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"companyId":      @"1000**",      //companyId
 *             @"secretKey":      @"*********",     //secretKey
 *             @"keyLen":         @"*********",   //算法长度
 *             @"keyType":        @"*********",   //算法类型 SM2 RSA1024 RSA2048
 *             @"p10"             @"*********"    // csr
 *             @"username":       @"*********"    // 用户名
 *                   };
 *  @param successBlock 请求成功后的回调
 *  @param fail 请求失败后的回调
 */
+(void )importP10:(NSDictionary *)data successBlock:(void (^)(id))successBlock fail:(void (^)(NSError *))fail;


#pragma  mark  生成证书

+(void )generateCert:(NSDictionary *)data successBlock:(void (^)(id))successBlock fail:(void (^)(NSError *))fail;

#pragma  mark  获取P7sign



typedef struct BT
{
    unsigned char *buf;
    size_t  len;
    int res;
} BUFF_POINT;
/**
 *  生成P7Sign
 *  @param buf      文件内容(明文)
 *  @param cert     证书内容(base编码)
 *  @param data     签名数据
 *
 *   data =@{
 *             @"appId"           @"**********"  //appId
 *             @"companyId":      @"1000**",      //companyId
 *             @"secretKey":      @"*********", //secretKey
 *             @"keyLen":         @"*********",   //算法长度
 *             @"keyType":        @"*********",   //算法类型 SM2 RSA1024 RSA2048
 *             @"username":       @"*********"    // 用户名
 *             @"pin":            @"*********", //pin
 *                   };
 *  @param successBlock 请求成功后的回调
 *  @param errorBlock 请求失败后的回调
 */
+(void)getP7Sign:(BUFF_POINT )buf andCert:(NSString *)cert andData:(NSDictionary *)data andSuccess:(void (^)(NSDictionary * successData))successBlock error:(void (^)(NSError* error))errorBlock;

/**
 *  P7验签
 *  @param sign      P7签名
 *  @param buf       文件内容(明文)
 */
+(void)P7SignVerify:(NSString *)sign andBuf:(BUFF_POINT )buf  andSuccess:(void (^)(NSDictionary * successData))successBlock ;


#pragma mark - 手机盾管理接口

#pragma mark 注册新用户
/**
 *  注册新用户
 *  data =@{
 *          @"username":     @"用户名：一般为手机号"，
 *          @"passwd":       @"********"
 *          @"email":        @"邮箱"
 *          @"comname":      @"公司名称"
 *          @"phone":        @"电话"
 *          @"companyId":    @"companyId"
 *          @"secretKey":    @"secretKey", 
 *                };
 *  @param successBlock      请求成功后的回调
 *  @param fail              请求失败后的回调
 */
+(void)registNewWith:(NSDictionary *) data successBlock:(void (^)(NSDictionary * successData))successBlock fail:(void (^)(NSError *))fail;

#pragma mark 获取用户是否存在
/**
 *  获取用户是否存在
 *  data =@{
 *          @"username":    @"用户名"，
 *          @"companyId":   @"companyId"
 *          @"secretKey":   @"secretKey"
 *                };
 *  @param successBlock     请求成功后的回调
 *  @param fail             请求失败后的回调
 */
+ (void)verifyUser:(NSDictionary *)data successBlock:(void (^)(NSDictionary * successData))successBlock fail:(void (^)(NSError *))fail;


#pragma mark 获取签名历史
/**
 *  获取签名历史
 *  data =@{
 *          @"username":    @"用户名：一般为手机号"，
 *          @"companyId":   @"companyId"
 *          @"secretKey":   @"secretKey"
 *                };
 *  @param successBlock     请求成功后的回调
 *  @param fail             请求失败后的回调
 */
+ (void)getSignHistory:(NSDictionary *)data successBlock:(void (^)(NSDictionary * successData))successBlock fail:(void (^)(NSError *))fail;

#pragma mark 获取证书
/**
 *  获取证书
 *  data =@{
 *          @"username":    @"用户名：      一般为手机号"，
 *          @"companyId":   @"companyId"
 *          @"secretKey":   @"secretKey"
 *          @"type":        @" "          算法类型  SM2/RSA1024/RSA2048
 *                };
 *  @param successBlock     请求成功后的回调
 *  @param fail             请求失败后的回调
 */
+(void)getCert:(NSDictionary *)data successBlock:(void (^)(NSDictionary * successData))successBlock fail:(void (^)(NSError *))fail;

#pragma mark 获取证书信息
/**
 *  获取证书信息
 *  data =@{
 *          @"username":       @"用户名：一般为手机号"，
 *          @"companyId":      @"companyId"
 *          @"secretKey":      @"secretKey"
 *          @"type":           @" "   算法类型  SM2/RSA1024/RSA2048
 *                };
 *  @param successBlock         请求成功后的回调
 *  @param fail                 请求失败后的回调
 */
+(void)getCertInfo:(NSDictionary *)data successBlock:(void (^)(NSDictionary * successData))successBlock fail:(void (^)(NSError *))fail;

#pragma mark 导入证书

/**
 *  导入证书
 *  data =@{
 *          @"username":        @"用户名：        一般为手机号"，
 *          @"companyId":       @"companyId"
 *          @"type":            @" "            算法类型  SM2/RSA1024/RSA2048
 *          @"signCert":        @"",            签名证书
 *          @"encCert":         @""             加密证书
 *          @"encPrivate":      @""             加密私钥
 *          @"secretKey":   @"secretKey"
 *          @"operType":@(1)  //0-6 0:all 1:signCert 2:encCert 3:encPrivate 4:signCert encCert 5:signCert encPrivate 6:encCert encPrivate
 *         }
 *  @param successBlock 请求成功后的回调
 *  @param fail 请求失败后的回调
 */
+(void)updateCert:(NSDictionary *)data successBlock:(void (^)(NSDictionary * successData))successBlock fail:(void (^)(NSError *))fail;

#pragma mark 登录

/**
 *  登录
 *  data =@{
 *          @"username":    @"用户名：一般为手机号"，
 *          @"companyId":   @"companyId"
 *          @"secretKey":   @"secretKey"
 *          @"passwd":      @"*****"
 *          };
 *  @param successBlock     请求成功后的回调
 *  @param fail             请求失败后的回调
 */
+(void)login:(NSDictionary *)data successBlock:(void (^)(NSDictionary * successData))successBlock fail:(void (^)(NSError *))fail;

#pragma mark - 数据存储
/**
 *  数据存储  把数据存储在沙盒路径下，以fileName命名
 *
 *  @param fileName     存储文件名
 *  @param byteData     存储数据
 *  @param length       数据长度
 *
 *  返回文件存储路径(NSString)
 */
+(NSString *)writeToFile:(NSString *)fileName andByteData:(Byte[])byteData andLength:(int)length;


#pragma mark - 指纹识别
+(void)FingerprintRecognition;

#pragma mark -    对称加解密
#pragma mark -SM4 加解密
/**
 *  SM4 ECB模式下加密
 *
 *  @param key            密钥
 *  @param operateData    待处理数据
 *   return               处理后数据
 */
+(NSString *)SM4_ENC_ecbWithkey:(NSString *)key andinput:(NSString *)operateData;

/**
 *  SM4 ECB模式下解密
 *
 *  @param key            密钥
 *  @param operateData    待处理数据
 *   return               处理后数据
 */
+(NSString *)SM4_DEC_ecbWithkey:(NSString *)key andinput:(NSString *)operateData;
/**
 *  SM4 CBC模式下加密
 *
 *  @param key          密钥
 *  @param operateData  待处理数据
 *  @param iv           initialization vector (updated after use)
 *  return              处理后数据
 */
+(NSString * )SM4_ENC_cbcWithkey:(NSString *)key andinput:(NSString *)operateData andiv:(unsigned char *) iv;
/**
 *  SM4 CBC模式下解密
 *
 *  @param key          密钥
 *  @param operateData  待处理数据
 *  @param iv           initialization vector (updated after use)
 *  return              处理后数据
 */
+(NSString * )SM4_DEC_cbcWithkey:(NSString *)key andinput:(NSString *)operateData andiv:(unsigned char *) iv;


#pragma mark - AES 加解密

typedef NSUInteger AESPadding;
NS_ENUM(AESPadding) {
    AESNoPadding  = 1,             //NOPadding
    AESPKCS5Padding  = 2,          //PKCS5Padding
};
/**
 *  AES ECB模式下加密
 *
 *  @param key            密钥
 *  @param operateData    待处理数据
 *   return               处理后数据
 */
+(NSString *)AES_ENC_ecbWithkey:(NSString *)key andinput:(NSString *)operateData andPadding:(AESPadding) AESPadding;

/**
 *  AES ECB模式下解密
 *
 *  @param key            密钥
 *  @param operateData    待处理数据
 *   return               处理后数据
 */
+(NSString *)AES_DEC_ecbWithkey:(NSString *)key andinput:(NSString *)operateData andPadding:(AESPadding) AESPadding;
/**
 *  AES CBC模式下加密
 *
 *  @param key          密钥
 *  @param operateData  待处理数据
 *  @param iv           initialization vector (updated after use)
 *  return              处理后数据
 */
+(NSString * )AES_ENC_cbcWithkey:(NSString *)key andinput:(NSString *)operateData andiv:(unsigned char [16]) iv andPadding:(AESPadding) AESPadding;
/**
 *  AES CBC模式下解密
 *
 *  @param key          密钥
 *  @param operateData  待处理数据
 *  @param iv           initialization vector (updated after use)
 *  return              处理后数据
 */
+(NSString * )AES_DEC_cbcWithkey:(NSString *)key andinput:(NSString *)operateData andiv:(unsigned char [16]) iv andPadding:(AESPadding) AESPadding;

#pragma mark - RSA

#pragma mark - 从手机盾公钥获取标准公钥
/**
 *  获取公钥
 *
 *  @param publicKey    手机盾RSA公钥
 *  return              公钥（base64编码后）
 */
+(NSString *)getStanderRSAPublicKey:(NSString *)publicKey;

#pragma mark 标准公钥加密

/**
 *  加密
 *
 *  @param publicKey    公钥（base64编码后）
 *  @param plain        明文（base64编码后）
 *  @param keylength    密钥长度（1024/2048）
 *  @param bl           是否填充
 *  return              密文（base64编码后）
 */
+(NSString *)rsaEncrypt:(NSString *)publicKey plain:(NSString *)plain keylength:(int)keylength  padding:(BOOL)bl;

#pragma mark 标准私钥解密
/**
 *  解密
 *
 *  @param privateKey    私钥（base64编码后）
 *  @param cipher        密文（base64编码
 *  return               明文（base64编码后）
 */
+(NSString *)rsaDecrypt:(NSString *)privateKey cipher:(NSString *)cipher;

#pragma mark - RSA 分割加解密


/**
 *  加密
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"username":     @"*********", //username
 *             @"companyId":    @"*********", //公司id
 *             @"keyLen":       @"*********", //密钥长度
 *             @"plainText":    @"*********", //明文信息（base64编码后）
 *           };
 *  @param successBlock         请求成功后的回调
 *  @param errorBlock           请求失败后的回调
 */

+(void)rsaEncrypt:(NSDictionary *)data successBlock:(void (^)(id ))successBlock errorBlock:(void(^)(NSError *))errorBlock;

/**
 *  解密
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"username":     @"*********", //username
 *             @"pin":          @"*********", //pin
 *             @"companyId":    @"*********", //公司id
 *             @"keyLen":       @"*********", //密钥长度
 *             @"ciphertext":   @"*********", //明文信息
 *             @"secretKey":    @"*********", //secretKey
 *           };
 *  @param successBlock         请求成功后的回调
 *  @param errorBlock           请求失败后的回调
 */
//RSA解密
+(void)rsaDecrypt:(NSDictionary *)data successBlock:(void (^)(NSDictionary *))successBlock errorBlock:(void(^)(NSError *))errorBlock;

#pragma mark - sm2分割加解密


/**
 *  加密
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"username":     @"*********", //用户id
 *             @"companyId":    @"*********", //公司id
 *             @"plainText":    @"*********", //明文信息
 *           };
 *  @param successBlock         请求成功后的回调
 *  @param errorBlock           请求失败后的回调
 */
+(void)SM2Encrypt:(NSDictionary *)data successBlock:(void (^)(id))successBlock errorBlock:(void(^)(NSError *))errorBlock;


/**
 *  解密
 *
 *  @param data     请求数据
 *
 *   data =@{
 *             @"username":     @"*********", //用户id
 *             @"companyId":    @"*********", //公司id
 *             @"keyLen":       @"*********", //密钥长度
 *             @"ciphertext":   @"*********", //密文信息
 *             @"secretKey":    @"*********", //secretKey
 *             @"pin":          @"*********", //pin
 *           };
 *  @param successBlock         请求成功后的回调
 *  @param errorBlock           请求失败后的回调
 */
+(void)SM2Decrypt:(NSDictionary *)data successBlock:(void (^)(id))successBlock errorBlock:(void(^)(NSError *))errorBlock;


#pragma mark - SM2完整加解密
/**
 *  加密
 *
 *  @param publicKey     公钥（base64编码后）
 *  @param plainText     请求数据
 *  return               返回密文/错误码
 */
+(NSString *)SM2Encrypt:(NSString *)publicKey andPlainText:(NSString *) plainText;

/**
 *  解密
 *
 *  @param privateKey     请求数据（base64编码后）
 *  @param ciphertext     请求数据
 *  return                返回明文/错误码
 */
+(NSString *)SM2Decrypt:(NSString *)privateKey andciphertext:(NSString *) ciphertext;

#pragma mark - 证书操作
#pragma mark-证书加密

/**
 *  证书加密
 *
 *  @param cert          证书（base64编码后）
 *  @param keyType       算法 SM2/RSA1024/RSA2048
 *  @param plainText     加密数据（base64编码后）
 *  @param keylength     算法长度 RSA 1024/2048  SM2默认256
 *  @param padding       是否填充 RSA加密用到 YES/NO
 *  return               返回密文（base64编码后）/错误码
 */
+(NSDictionary *)EncryptWithCert:(NSString *)cert alg:(NSString *)keyType andPlainText:(NSString *)plainText keylength:(int)keylength padding:(BOOL)padding;

#pragma mark-证书验签
/**
 *  证书验签
 *
 *  @param cert          证书（base64编码后）
 *  @param alg           算法标识 RSA/SM2
 *  @param signature     签名值  （base64编码后）
 *  @param e             e       签名时哈希明文
 *  return               验签结果/错误码
 */
+(NSString *)VerifyWithCert:(NSString *)cert alg:(NSString *)alg signature:(NSString *)signature e:(NSString *)e;

#pragma mark - 定制接口
/**
 *  四川CA 解数字信封并解密
 *
 *  @param companyId            companyId
 *  @param username             username
 *  @param pin                  pin
 *  @param secretKey            secretKey
 *  @param userSeal             userSeal
 *  @param encPrivateKeyUser    encPrivateKeyUser
 *  @param userIV               userIV
 *  @param alg                  alg
 *  @param mode                 mode 对称解密模式：ECB/CBC
 *  @param ciphertext           ciphertext
 *  @param successBlock 请求成功后的回调
 *  @param errorBlock 请求失败后的回调
 */



+(void)decryptoCompanyId:(NSString *)companyId username:(NSString *)username pin:(NSString *)pin  secretKey:(NSString *)secretKey userSeal:(NSString *)userSeal encPrivateKeyUser:(NSString *)encPrivateKeyUser userIV:(NSString *)userIV alg:(NSString *)alg mode:(NSString *)mode ciphertext:(NSString *)ciphertext successBlock:(void(^)(id))successBlock errorBlock:(void(^)(NSError *))errorBlock;

#pragma mark - 国密DER编码
/**
 *  签名值转der编码
 *
 *  @param sign  手机盾签名（base64编码后）
 *  return der签名值
 */
+(NSString *)DEREncodeSM2Signature:(NSString *)sign;


/**
 *  der签名值转手机盾签名值
 *
 *  @param derSign  手机盾签名（base64编码后）
 *  return 返回手机盾签名值
 */

+(NSString *)DERDecodeSM2Signature:(NSString *)derSign;
@end
